#ifndef PORT_HW_C_
#define PORT_HW_C_
/******************************************************************
| includes
| 1) system and project includes
| 2) needed interfaces from external units
| 3) internal and external interfaces from this unit
|-----------------------------------------------------------------*/
#include "Port_Hw.h"
#include "Platform_Lib.h"

/*******************************************************************
| function implementations (scope: module-local)
|------------------------------------------------------------------*/

/**********************************************************************
* Function Prototype: void Port_Hw_Update_PcValue(uint8 index, Port_ConfigTypeRef tmpPortCfg)
* Service ID:
* Sync/Asyn:
* Re-Entrancy:
* Parameters description
* 	(in): index: index means the pin's array index in Port_ConfigTbl
* 	(out):
* Return Value:
* Caller:
* Call Function:
* Description: update the port control register of the pin specified by index
* Author:
* Time:
***************************************************************************
*/
void Port_Hw_Update_PcValue(uint8 index, Port_ConfigTypeRef tmpPortCfg)
{
	PortPinIdType CurPinId = UsrPIdToHwPIdMapTbl[tmpPortCfg[index].PortPinId];/*get the hardware pin id*/
	PortPinIdType PortId = GET_PORT_INDEX(CurPinId);/*get the port index*/
	PortPinIdType PinId = GET_PIN_INDEX(CurPinId);/*get the pin index*/
	uint8 PcIndex = PinId >> 2;/*get the position of the port control register*/
	uint8 PcOffset = PinId - (PcIndex << 2);/*get the start bit position of the port control register*/

	switch (GET_PORT_PIN_DYNDIR(index))/*check the direction of this port pin*/
	{
		case PORT_PIN_DYN_DIR_IN:
		{
			/*direction is input, set the input port control code*/
			Write_Port_PC(PortId, PcIndex, PcOffset, ((uint8)GET_PORT_PIN_PC_IN(index)));
			break;
		}
		case PORT_PIN_DYN_DIR_OUT:
		{
			/*direction is output, set the output port control code*/
			Write_Port_PC(PortId, PcIndex, PcOffset, ((uint8)GET_PORT_PIN_PC_OUT(index)));
			break;
		}
		default:
			break;
	}
}
/**********************************************************************
* Function Prototype: void Port_Hw_Init(uint8 index, Port_ConfigTypeRef tmpPortCfg)
* Service ID:
* Sync/Asyn:
* Re-Entrancy:
* Parameters description
* 	(in): index: index means the pin's array index in Port_ConfigTbl
* 	(out):
* Return Value:
* Caller:
* Call Function:
* Description: initial the hardware environment of the port pin specified by index
* Author:
* Time:
***************************************************************************
*/
void Port_Hw_Init(uint8 index, Port_ConfigTypeRef tmpPortCfg)
{
	Port_ConfigTypeRef Port_ConfigPtr = &tmpPortCfg[index];/*get the configuration of the pin*/
	PortPinIdType CurPinId = UsrPIdToHwPIdMapTbl[Port_ConfigPtr->PortPinId];/*get the hardware pin id*/
	PortPinIdType PortId = GET_PORT_INDEX(CurPinId);/*get the port index*/
	PortPinIdType PinId = GET_PIN_INDEX(CurPinId);/*get the pin index*/
	uint8 PdIndex;/*pad driver index of this pin*/

	/*check the direction of this pin*/
	if(GET_PORT_PIN_DYNDIR(index) == PORT_PIN_DYN_DIR_OUT || CHECK_PORT_PIN_DIR_CHANGEABLE(index) == TRUE )
	{
		/*if the direction of this pin may be output, then set the pad driver code of this pin*/
		PdIndex = UsrPIdToPdIdxMapTbl[Port_ConfigPtr->PortPinId];
		Mcal_ResetENDINIT();
		Write_Port_PD(PortId, PdIndex, (uint8)GET_PORT_PIN_PD_OUT(index));
		Mcal_SetENDINIT();
	}

	/*if the function mode is GPIO mode, initial the value of the output*/
	if(CHECK_PORT_PIN_FUNC_GPIO(index) == TRUE)
	{
		/*check the output level*/
		switch(Port_ConfigPtr->PortPinLevelValue)
		{
			case PORT_PIN_LEVEL_LOW:
			{
				/*set output to low by changing the value of OMR register for the pin*/
				Set_Port_PR(PortId, PinId);
				Clear_Port_PS(PortId, PinId);
				break;
			}
			case PORT_PIN_LEVEL_HIGH:
			{
				/*set output to high by changing the value of OMR register for the pin*/
				Clear_Port_PR(PortId, PinId);
				Set_Port_PS(PortId, PinId);
				break;
			}
			default :
				break;
		}
	}
	/*check emergence stop function*/
	if(CHECK_PORT_PIN_EM_STOP_EN(index) == TRUE)
	{
		/*check the port pin's emergence stop output level*/
		if(CHECK_PORT_PIN_EM_STOP_LEVEL(index) == TRUE)
		{
			/*set output to high by changing the value of OMR register for the pin*/
			Clear_Port_PR(PortId, PinId);
			Set_Port_PS(PortId, PinId);
		}
		else
		{
			/*reset output to low by changing the value of OMR register for the pin*/
			Set_Port_PR(PortId, PinId);
			Clear_Port_PS(PortId, PinId);
		}
		Mcal_ResetENDINIT();
		Set_Port_EN(PortId, PinId);
		Mcal_SetENDINIT();
	}
	/*after setting the output value, update port control code of this pin .*/
	Port_Hw_Update_PcValue(index, tmpPortCfg);
	return ;
}

#endif /*PORT_HW_C_*/
